import os
import sys
import json
import pymongo
from pytdx.params import TDXParams

dirname = os.path.dirname(__file__)
plugin_path = os.path.join(dirname, 'venv', 'Lib', 'site-packages', 'PyQt5', 'Qt5', 'plugins', 'platforms')
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = plugin_path

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from objdict import ObjDict
from collections import namedtuple
from bak import Dialog
from pytdx.hq import TdxHq_API


class MainWindow(QWidget):
    def __init__(self, parent=None):
        super(QWidget, self).__init__(parent)
        self.ui = Dialog.Ui_Dialog()
        self.ui.setupUi(self)
        self.connectChange()

    def do_timer_timeout(self):  # 定时中断相应
        curTime = QDateTime.currentDateTime()  # 获取当前时间
        timePlay = curTime.toString('yyyy-MM-dd  dddd  hh:mm:ss')
        self.ui.timeLabel.setText(timePlay)

    def areaRadioChecked(self):
        _translate = QCoreApplication.translate
        if (self.ui.radioButton_s.isChecked() == True):
            self.ui.label_2.setText(_translate("Dialog", "卖 出 价："))
            self.ui.label_5.setText(_translate("Dialog", "持仓数量："))
        else:
            self.ui.label_2.setText(_translate("Dialog", "买 入 价："))
            self.ui.label_5.setText(_translate("Dialog", "资金余额："))

    def connectChange(self):
        self.timer = QTimer()  # 创建定时器
        self.timer.start(1000)  # 定时周期1000ms
        self.timer.timeout.connect(self.do_timer_timeout)
        self.ui.radioButton_50.setChecked(True)
        self.ui.radioButton_b.setChecked(True)
        self.ui.radioButton_etf.setChecked(True)
        self.ui.buttonGroup_arae.idToggled.connect(self.areaRadioChecked)
        self.logic = CalculateLogic(self.ui)
        self.ui.saveButton.clicked.connect(self.logic.saveSetting)
        self.ui.doubleSpinBox_sl.valueChanged.connect(self.logic.tableChanged)
        self.ui.doubleSpinBox_price.valueChanged.connect(self.logic.tableChanged)
        self.ui.doubleSpinBox_ss.valueChanged.connect(self.logic.tableChanged)
        self.ui.spinBox.valueChanged.connect(self.logic.tableChanged)
        self.ui.buttonGroup_arae.buttonClicked.connect(self.logic.tableChanged)
        self.ui.buttonGroup_ratio.buttonClicked.connect(self.logic.tableChanged)
        self.ui.buttonGroup_type.buttonClicked.connect(self.logic.tableChanged)
        self.ui.tabList.currentChanged.connect(self.logic.tabBarChanged)

class CalculateLogic(object):
    def __init__(self, object):
        self.ui = object
        self.setting = jsonUnit('./setting.json')
        self.settingJson = self.setting.readJsonFile()
        self.loadSetting(self.settingJson)
        self.defaultTable()

    def defaultTable(self):
        self.ui.tableWidget.setColumnWidth(1, 95)
        self.ui.tableWidget.setColumnWidth(2, 95)
        self.ui.tableWidget.setColumnWidth(3, 120)
        self.ui.tableWidget.setColumnWidth(4, 120)
        self.ui.tableWidget.setColumnWidth(5, 121)
        self.ui.tableWidget.setColumnWidth(6, 120)
        newItem = QTableWidgetItem('1.00:1')
        newItem.setTextAlignment(Qt.AlignRight | Qt.AlignBottom)
        self.ui.tableWidget.setItem(1, 0, newItem)
        newItem = QTableWidgetItem('2.00:1')
        newItem.setTextAlignment(Qt.AlignRight | Qt.AlignBottom)
        self.ui.tableWidget.setItem(2, 0, newItem)
        newItem = QTableWidgetItem('3.00:1')
        newItem.setTextAlignment(Qt.AlignRight | Qt.AlignBottom)
        self.ui.tableWidget.setItem(3, 0, newItem)
        newItem = QTableWidgetItem('4.00:1')
        newItem.setTextAlignment(Qt.AlignRight | Qt.AlignBottom)
        self.ui.tableWidget.setItem(4, 0, newItem)
        newItem = QTableWidgetItem('5.00:1')
        newItem.setTextAlignment(Qt.AlignRight | Qt.AlignBottom)
        self.ui.tableWidget.setItem(5, 0, newItem)

    def _priceNumber(self, ratio, arae, income, price, money):
        if (ratio == 'radioButton_40'):
            if (income < 1.6):
                kelly = 0
            elif (income >= 1.6 and income <= 2.6):
                kelly = 0.1
            elif (income > 2.6 and income <= 3.7):
                kelly = 0.2
            else:
                kelly = 0.3
        elif (ratio == 'radioButton_50'):
            if (income < 1.5):
                kelly = 0
            elif (income >= 1.5 and income < 1.8):
                kelly = 0.1
            elif (income >= 1.8 and income <= 2.6):
                kelly = 0.25
            elif (income > 2.6 and income <= 3.7):
                kelly = 0.33
            else:
                kelly = 0.4
        else:
            if (income < 1.5):
                kelly = 0.2
            elif (income >= 1.5 and income <= 2.6):
                kelly = 0.4
            elif (income > 2.6 and income <= 3.7):
                kelly = 0.47
            else:
                kelly = 0.55
        if(arae == 'radioButton_b'):
            return int(money / price / 100) * kelly * 100
        else:
            return int(money * kelly / 100) * 100

    def _calculateProfits(self, price, ss, sl, money, row, column):
        if (column == 0):
            income = abs((ss - price) / (price - sl))
            newItem = QTableWidgetItem(str(round(income, 2)) + ':1')
            newItem.setTextAlignment(Qt.AlignRight | Qt.AlignBottom)
            self.ui.tableWidget.setItem(0, 0, newItem)
        elif (column == 1):    # 计算【止损价】
            newItem = QTableWidgetItem('￥' + str(sl))
            newItem.setTextAlignment(Qt.AlignRight | Qt.AlignBottom)
            self.ui.tableWidget.setItem(row, 1, newItem)
        elif (column == 2):     # 计算【止盈价】
            if (row > 0):
                newSL = abs(price - sl)
                newItem = QTableWidgetItem('￥' + str(round(price + newSL * row, 3)))
            else:
                newItem = QTableWidgetItem('￥' + str(ss))
            newItem.setTextAlignment(Qt.AlignRight | Qt.AlignBottom)
            self.ui.tableWidget.setItem(row, 2, newItem)
        elif (column >= 3):
            arae = self.ui.buttonGroup_arae.checkedButton().objectName()
            ratio = self.ui.buttonGroup_ratio.checkedButton().objectName()
            type = self.ui.buttonGroup_type.checkedButton().objectName()
            if (row == 0):
                income = abs((ss - price) / (price - sl))
                number = self._priceNumber(ratio, arae, round(income, 2), price, money)
                grossProfit = abs(price - ss) * number
                if(number != 0):
                    if(arae == 'radioButton_b'):
                        buyCost = self._calculateCost(type, 'radioButton_b', price, number)
                        sellCost = self._calculateCost(type, 'radioButton_s', ss, number)
                    else:
                        buyCost = self._calculateCost(type, 'radioButton_s', price, number)
                        sellCost = self._calculateCost(type, 'radioButton_b', ss, number)
                else:
                    buyCost = 0
                    sellCost  = 0
            else:
                number = self._priceNumber(ratio, arae, row, price, money)
                if (arae == 'radioButton_b'):
                    newSs = round(price + abs(price - sl) * row, 3)
                else:
                    newSs = round(price - abs(price - sl) * row, 3)
                if (number != 0):
                    if (arae == 'radioButton_b'):
                        buyCost = self._calculateCost(type, 'radioButton_b', price, number)
                        sellCost = self._calculateCost(type, 'radioButton_s', newSs, number)
                    else:
                        buyCost = self._calculateCost(type, 'radioButton_s', price, number)
                        sellCost = self._calculateCost(type, 'radioButton_b', newSs, number)
                else:
                    buyCost = 0
                    sellCost  = 0
                grossProfit = abs(price - newSs) * number
            newItem = QTableWidgetItem(str(number))
            newItem.setTextAlignment(Qt.AlignRight | Qt.AlignBottom)
            self.ui.tableWidget.setItem(row, 3, newItem)
            newItem = QTableWidgetItem('￥' + str(round(grossProfit, 2)))
            newItem.setTextAlignment(Qt.AlignRight | Qt.AlignBottom)
            self.ui.tableWidget.setItem(row, 4, newItem)
            newItem = QTableWidgetItem('￥' + str(round(buyCost + sellCost, 2)))
            newItem.setTextAlignment(Qt.AlignRight | Qt.AlignBottom)
            self.ui.tableWidget.setItem(row, 5, newItem)

    def _calculateCost(self, type, arae, price, number):
        money = price * number
        cost = 0
        json = self.settingJson
        if(type == 'radioButton_etf'):
            cost = cost + money * json.etf.doubleSpinBox_0.value * 0.01
            if (arae == 'radioButton_s' and type == 'radioButton_sh'):
                cost += money * json.etf.doubleSpinBox_1.value * 0.01
            cost = cost + money * json.etf.doubleSpinBox_2.value * 0.01
            cost = cost + money * json.etf.doubleSpinBox_3.value * 0.01
            cost = cost + money * json.etf.doubleSpinBox_4.value * 0.01
            if(json.etf.checkBox_etf.value != True):
                if(cost<5):
                    cost = 5 if cost < 5 else cost
        else:
            cost += money * json.stock.doubleSpinBox_0.value * 0.01
            if (arae == 'radioButton_s' and type == 'radioButton_sh'):
                cost += money * json.stock.doubleSpinBox_1.value * 0.01
            cost = cost + money * json.stock.doubleSpinBox_2.value * 0.01
            cost = cost + money * json.stock.doubleSpinBox_3.value * 0.01
            cost = cost + money * json.stock.doubleSpinBox_4.value * 0.01
            if (json.stock.checkBox_stock.value != True):
                if (cost < 5):
                    cost = 5 if cost < 5 else cost
        return cost

    def tableChanged(self):
        price = self.ui.doubleSpinBox_price.value()
        ss = self.ui.doubleSpinBox_ss.value()
        sl = self.ui.doubleSpinBox_sl.value()
        money = self.ui.spinBox.value()
        if (sl != 0):
            for i in range(6):
                self._calculateProfits(price, ss, sl, money, i, 1)
        if (ss != 0):
            self._calculateProfits(price, ss, sl, money, 0, 0)
        if (price != 0 and sl != 0):
            for i in range(1, 6):
                self._calculateProfits(price, ss, sl, money, i, 2)
        if (ss != 0 and price != 0 and sl != 0):
            self._calculateProfits(price, ss, sl, money, 0, 0)
            self._calculateProfits(price, ss, sl, money, 0, 2)
        if (price != 0 and sl != 0 and ss != 0 and money != 0):
            for i in range(6):
                self._calculateProfits(price, ss, sl, money, i, 3)

    def loadSetting(self, data):
        stock = data.stock
        etf = data.etf
        self.ui.checkBox_stock.setChecked(stock.checkBox_stock.value)
        self.ui.checkBox_etf.setChecked(etf.checkBox_etf.value)
        self.ui.doubleSpinBox_stock_0.setValue(stock.doubleSpinBox_0.value)
        self.ui.doubleSpinBox_stock_1.setValue(stock.doubleSpinBox_1.value)
        self.ui.doubleSpinBox_stock_2.setValue(stock.doubleSpinBox_2.value)
        self.ui.doubleSpinBox_stock_3.setValue(stock.doubleSpinBox_3.value)
        self.ui.doubleSpinBox_stock_4.setValue(stock.doubleSpinBox_4.value)
        self.ui.doubleSpinBox_etf_0.setValue(etf.doubleSpinBox_0.value)
        self.ui.doubleSpinBox_etf_1.setValue(etf.doubleSpinBox_1.value)
        self.ui.doubleSpinBox_etf_2.setValue(etf.doubleSpinBox_2.value)
        self.ui.doubleSpinBox_etf_3.setValue(etf.doubleSpinBox_3.value)
        self.ui.doubleSpinBox_etf_4.setValue(etf.doubleSpinBox_4.value)

    def saveSetting(self):
        data = ObjDict()
        data.stock = ObjDict()
        data.stock.checkBox_stock = ObjDict()
        data.stock.checkBox_stock.label = '股票免五'
        data.stock.checkBox_stock.value = self.ui.checkBox_stock.isChecked()
        data.stock.doubleSpinBox_0 = ObjDict()
        data.stock.doubleSpinBox_0.label = '股票印花税'
        data.stock.doubleSpinBox_0.value = self.ui.doubleSpinBox_stock_0.value()
        data.stock.doubleSpinBox_1 = ObjDict()
        data.stock.doubleSpinBox_1.label = '股票过户费'
        data.stock.doubleSpinBox_1.value = self.ui.doubleSpinBox_stock_1.value()
        data.stock.doubleSpinBox_2 = ObjDict()
        data.stock.doubleSpinBox_2.label = '股票经手费'
        data.stock.doubleSpinBox_2.value = self.ui.doubleSpinBox_stock_2.value()
        data.stock.doubleSpinBox_3 = ObjDict()
        data.stock.doubleSpinBox_3.label = '股票证管费'
        data.stock.doubleSpinBox_3.value = self.ui.doubleSpinBox_stock_3.value()
        data.stock.doubleSpinBox_4 = ObjDict()
        data.stock.doubleSpinBox_4.label = '股票佣金'
        data.stock.doubleSpinBox_4.value = self.ui.doubleSpinBox_stock_4.value()
        data.etf = ObjDict()
        data.etf.checkBox_etf = ObjDict()
        data.etf.checkBox_etf.label = 'ETF免五'
        data.etf.checkBox_etf.value = self.ui.checkBox_etf.isChecked()
        data.etf.doubleSpinBox_0 = ObjDict()
        data.etf.doubleSpinBox_0.label = 'ETF印花税'
        data.etf.doubleSpinBox_0.value = self.ui.doubleSpinBox_etf_0.value()
        data.etf.doubleSpinBox_1 = ObjDict()
        data.etf.doubleSpinBox_1.label = 'ETF过户费'
        data.etf.doubleSpinBox_1.value = self.ui.doubleSpinBox_etf_1.value()
        data.etf.doubleSpinBox_2 = ObjDict()
        data.etf.doubleSpinBox_2.label = 'ETF经手费'
        data.etf.doubleSpinBox_2.value = self.ui.doubleSpinBox_etf_2.value()
        data.etf.doubleSpinBox_3 = ObjDict()
        data.etf.doubleSpinBox_3.label = 'ETF证管费'
        data.etf.doubleSpinBox_3.value = self.ui.doubleSpinBox_etf_3.value()
        data.etf.doubleSpinBox_4 = ObjDict()
        data.etf.doubleSpinBox_4.label = 'ETF佣金'
        data.etf.doubleSpinBox_4.value = self.ui.doubleSpinBox_etf_4.value()
        self.setting.writeJsonFile(data)
        self.settingJson = data
        return

    def tabBarChanged(self):
        if self.ui.tabList.tabBar().currentIndex() == 2:
            api = TdxHq_API()
            with api.connect('119.147.212.81', 7709):
                client = pymongo.MongoClient(host='localhost', port=27017)
                db = client.stock
                collection = db.block_sz
                for o in api.get_and_parse_block_info(TDXParams.BLOCK_SZ):
                    collection.insert_one(o)
                collection = db.block_default
                for o in api.get_and_parse_block_info(TDXParams.BLOCK_DEFAULT):
                    collection.insert_one(o)
                collection = db.block_fg
                for o in api.get_and_parse_block_info(TDXParams.BLOCK_FG):
                    collection.insert_one(o)
                collection = db.block_gn
                for o in api.get_and_parse_block_info(TDXParams.BLOCK_GN):
                    collection.insert_one(o)
                collection = db.stock
                for o in api.get_security_list(0, 0):
                    collection.insert_one(o)
                for o in api.get_security_list(1, 0):
                    collection.insert_one(o)

            '''
            for block_zs in BlockReader().get_df("D:\通达信金融终端(开心果整合版)V2023.04\T0002\hq_cache/block_zs.dat", BlockReader_TYPE_GROUP):
                lines = block_zs.strip().split("\n")
                print(lines)
            '''


class jsonUnit(object):
    def __init__(self, jsonFile):
        self.settinfJsonFile = jsonFile

    def dict2obj(self, object):
        if isinstance(object, dict):
            return namedtuple(
                'struct', object.keys()
            )(
                *(self.dict2obj(val) for val in object.values())
            )
        elif isinstance(object, (tuple, list, set, frozenset)):
            return type(object)(self.dict2obj(_) for _ in object)
        else:
            return object

    def readJsonFile(self):
        with open(self.settinfJsonFile, 'r', encoding='utf-8') as f:
            data = self.dict2obj(json.load(f))
        return data

    def writeJsonFile(self, jsonData):
        with open(self.settingJsonFile, 'w', encoding='utf-8') as f:
            json.dump(jsonData, f, ensure_ascii=False)
        return

    def runMongoDb(self, data):
        try:
            mongoPath = os.path.normpath(os.path.abspath(os.curdir) + "/mongodb")
            binFile = os.path.normpath(mongoPath + "/bin/mongod.exe")
            dbPath = os.path.normpath(mongoPath + "/data")
            logPath = os.path.normpath(mongoPath + "/log/mongodb.log")
            client = pymongo.MongoClient(host='localhost', port=27017)
        except:
            print("Windows service MongoDb Service NOT run")
            os.system(binFile + ' --dbpath ' + dbPath + ' --directoryperdb --logpath ' + logPath + ' --logappend')
            client = pymongo.MongoClient(host='localhost', port=27017)
        else:
            print("Windows service MongoDb Service run")
        db = client.stock
        collection = db.user
        collection.insert_one(data)
        return

if __name__ == '__main__':
    myapp = QApplication(sys.argv)
    myDlg = MainWindow()
    myDlg.show()
    sys.exit(myapp.exec_())
